#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/8/4 20:58
# @Author  : XH
# @File    : run_tests.py
# @Software: PyCharm
"""
host:
    dev: http://192.168.27.88:20006
    test: http://192.168.27.88:20006
    prod: http://192.168.27.88:20006
    pure_test: http://192.168.27.88:20001
    default: pure_test
admin_account:
    username: "iFlow_sys"
    password: "iFlow20220901"
path:
  login: /api/app/account/login

package:
    allure_path: .\package\allure-2.34.0\bin\allure.bat

pytest_config:
  maxfail: 3
  disable_warnings: true
  capture: no
  run_case_path: ""            # 为空时执行全部用例
  allure_results_dir: "allure-results"
  open_browser: true

wechat:
  enable: false
  webhook: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx"

#email:
#  from: "your@email.com"
#  to: "target@email.com"
#  password: "emailpassword"
#  smtp_server: "smtp.xxx.com"
#  smtp_port: 587

"""

import pytest
import subprocess
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from utils.handle_logger import mylog
from utils.handle_path import REPORT_DIR, CONF_DIR
from utils.handle_yaml import HandleYaml


import os
import shutil
import subprocess
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import requests

from utils.handle_logger import mylog
from utils.handle_path import CONF_DIR, REPORT_DIR, CASES_DIR
from utils.handle_yaml import HandleYaml


class TestRunner:
    def __init__(self):
        self.config = HandleYaml(CONF_DIR, "env.yaml").read_yaml()
        self.pytest_cfg = self.config.get("pytest_config", {})
        self.wechat_cfg = self.config.get("wechat", {})
        self.email_cfg = self.config.get("email", {})

        # 公共路径
        """
        优先从环境变量中获取 RUN_CASE_PATH，如果没有设置环境变量，则使用配置文件中的默认值。
        """
        self.run_case_path = os.environ.get("RUN_CASE_PATH", self.pytest_cfg.get("run_case_path", ""))
        self.maxfail = self.pytest_cfg.get("maxfail", 3)
        self.capture = os.environ.get("PYTEST_CAPTURE", self.pytest_cfg.get("capture", "no"))
        self.disable_warnings = self.pytest_cfg.get("disable_warnings", True)
        self.allure_result_dir = os.path.join(REPORT_DIR, self.pytest_cfg.get("allure_results_dir", "allure-results"))

        self.case_path = os.path.join(CASES_DIR, self.run_case_path) if self.run_case_path else CASES_DIR
        self.allure_cli = self.config.get("package", {}).get("allure_path")
        self.allure_report_output_dir = None
        self.open_browser = self.pytest_cfg.get("open_browser", False)

    def run(self):
        """主流程：运行测试 + 生成报告 + 通知"""
        self.run_pytest()
        self.generate_allure_report()
        #self.send_test_results_email()
        #self.send_wechat_notification()

    def run_pytest(self):
        if not os.path.exists(self.case_path):
            raise FileNotFoundError(f"测试用例路径不存在: {self.case_path}")

        if os.path.exists(self.allure_result_dir):
            shutil.rmtree(self.allure_result_dir)

        pytest_args = [
            f'--maxfail={self.maxfail}',
            f'--capture={self.capture}',
            f'--alluredir={self.allure_result_dir}'
        ]
        if self.disable_warnings:
            pytest_args.append('--disable-warnings')

        pytest_args.append(self.case_path)

        mylog.info(f"执行测试用例路径: {self.case_path}")
        mylog.info(f"pytest命令参数: {' '.join(pytest_args)}")

        result = subprocess.run(['pytest'] + pytest_args, capture_output=True, text=True, encoding='utf-8')
        if result.returncode == 0:
            mylog.info("✅ 所有测试通过")
        else:
            mylog.error("❌ 测试失败，请查看详细日志")
            print(result.stdout)

    def generate_allure_report(self):
        if not self.allure_cli or not os.path.exists(self.allure_cli):
            raise FileNotFoundError(f"Allure CLI 路径无效或不存在: {self.allure_cli}")

        if not os.path.exists(self.allure_result_dir):
            raise FileNotFoundError(f"Allure 结果目录不存在: {self.allure_result_dir}")

        current_date = datetime.now().strftime('%m-%d-%H-%M')
        self.allure_report_output_dir = os.path.join(REPORT_DIR, current_date)
        os.makedirs(self.allure_report_output_dir, exist_ok=True)

        result = subprocess.run([self.allure_cli, 'generate', self.allure_result_dir, '-o', self.allure_report_output_dir, '--clean'], text=True)
        if result.returncode == 0:
            mylog.info(f"✅ Allure 报告生成成功：{self.allure_report_output_dir}")
        else:
            mylog.error("❌ Allure 报告生成失败")
        if self.open_browser:
            subprocess.run([self.allure_cli, 'serve', self.allure_report_output_dir])

    def send_test_results_email(self):
        if not self.email_cfg:
            return

        subject = "测试结果报告"
        body = "测试已完成，详情请查看 Allure 测试报告或 Jenkins 输出日志。"

        from_email = self.email_cfg.get("from")
        password = self.email_cfg.get("password")
        to_email = self.email_cfg.get("to")
        smtp_server = self.email_cfg.get("smtp_server")
        smtp_port = self.email_cfg.get("smtp_port", 587)

        msg = MIMEMultipart()
        msg['From'] = from_email
        msg['To'] = to_email
        msg['Subject'] = subject
        msg.attach(MIMEText(body, 'plain'))

        try:
            server = smtplib.SMTP(smtp_server, smtp_port)
            server.starttls()
            server.login(from_email, password)
            server.sendmail(from_email, to_email, msg.as_string())
            server.quit()
            mylog.info("📧 邮件发送成功")
        except Exception as e:
            mylog.error(f"❌ 邮件发送失败: {e}")

    def send_wechat_notification(self):
        if not self.wechat_cfg.get("enable", False):
            mylog.info("🔕 企业微信通知未启用")
            return

        webhook = self.wechat_cfg.get("webhook")
        if not webhook:
            mylog.warning("⚠️ 未配置企业微信 webhook 地址")
            return

        message = {
            "msgtype": "markdown",
            "markdown": {
                "content": f"""### ✅ 自动化测试完成\n> 执行人: 测试系统 🤖  \n> 执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}  \n> 报告地址: [点击查看报告]({self.allure_report_output_dir})  \n"""
            }
        }

        try:
            response = requests.post(url=webhook, json=message)
            if response.status_code == 200 and response.json().get("errcode") == 0:
                mylog.info("📨 企业微信消息发送成功")
            else:
                mylog.error(f"❌ 企业微信发送失败: {response.text}")
        except Exception as e:
            mylog.error(f"❌ 企业微信通知异常: {e}")



# 主函数：集成所有功能
if __name__ == '__main__':
    TestRunner().run()